/*******************************************************************************
 * Copyright (c) 2012, 2013 XML-Print Project.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     XML-Print Project - initial API and implementation
 ******************************************************************************/
package info.xmlprint.ui.format;

import java.util.HashMap;
import java.util.Map;

import info.xmlprint.core.format.Format;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;

public class GuiCommon {

	//
	protected String[] itemListUnits = { "cm", "mm", "pc", "pt", "px", "in" };

	protected Map<String, InternationalTransform> internationalMap = new HashMap<String, InternationalTransform>();

	// Postfix für FootnoteComposite
	protected String[] postfixItems = new String[] { "", ")", "]", "*" };
	protected String[] typeItems = new String[] { "Footnote", "Endnote" };

	protected HashMap<Integer, Control[]> ghm = new HashMap<Integer, Control[]>(); // setup new Hashmap;
	protected HashMap<Integer, Control[]> cwhm = new HashMap<Integer, Control[]>(); // setup new Hashmap;
	protected HashMap<Integer, Combo> cdhm = new HashMap<Integer, Combo>(); // setup new Hashmap;
	
	public GuiCommon() {
	};

	protected void setCombo(Combo combo, String str) {

		if (str == null)
			return;

		/*
		 * // Todo: zu verbessen if (str.equals("justify")) { str =
		 * GuiMessages.Stileditor_ParagraphFormat_Alignment_Justified; } else if
		 * (str.equals("left")) { str =
		 * GuiMessages.Stileditor_ParagraphFormat_Alignment_Left; } else if
		 * (str.equals("right")) { str =
		 * GuiMessages.Stileditor_ParagraphFormat_Alignment_Right; } else if
		 * (str.equals("center")) { str =
		 * GuiMessages.Stileditor_ParagraphFormat_Alignment_Center;
		 * 
		 * }
		 */
		int index = -1;
		for (int i = 0; i < combo.getItems().length; i++)
			if (combo.getItems()[i].equals(str)) {
				index = i;
				break;
			}

		if (index > -1) {
			combo.select(index);
		}

	}

	protected String[] getItemListUnits() {
		return itemListUnits;
	}

	protected String readCombo(Combo combo) {
		if (combo.getSelectionIndex() > -1) {
			return combo.getItem(combo.getSelectionIndex());
		}
		return "";
	}

	protected void setSpinnerCombo(Spinner spinner, Combo combo, String str) {

		if (str == null)
			return;

		String number = str.replaceAll("[a-zA-Z\\s%]*", "");
		String unit = str.replaceAll("-?\\d*[,.]?\\d*", "");

		if (unit == null || unit.equals(""))
			unit = "";

		double i = 0;
		if (!number.equals("")) {
			i = Double.parseDouble(number)
					* (Math.pow(10, spinner.getDigits()));
		}

		spinner.setSelection((int) i);
		setCombo(combo, unit);
	}

	protected String readSpinnerCombo(Spinner spinner, Combo combo) {
		if (combo.getText().equalsIgnoreCase("auto")) // special case
			return ("auto");
		else if (combo.getText().equalsIgnoreCase("*")) // another special case
			return ("*");
		else
			return ((float) spinner.getSelection())
				/ (Math.pow(10, spinner.getDigits())) + readCombo(combo);
	}
	
	protected GridData getGD(int fill, int span, int w, int h) {
		GridData gridData;
		if (fill != 0)
			gridData = new GridData(fill);
		else
			gridData = new GridData();

		if (span != 0)
			gridData.horizontalSpan = span;

		if (w != 0)
			gridData.widthHint = w;

		if (h != 0)
			gridData.heightHint = h;

		return gridData;
	}

	protected void addLabel(Composite parentComp, String str) {
		Label label = new Label(parentComp, SWT.NONE);
		label.setText(str);
		GridData gd = new GridData();
		gd.horizontalAlignment = GridData.END;
		label.setLayoutData(gd);

	}

	/*
	 * 
	 */
	protected void controlsInit(final Button standardButton,
			final Button inherit, final Map<String, Control[]> controlMap,
			final Map<String, Control> checkBoxMap, final Format format) {

		final String[] checkboxArr = new String[] { "space-before.maximum",
				"space-before.minimum", "space-after.maximum",
				"space-after.minimum" };

		// Eventhandler für die Elemente, so dass bei Änderung "Standard"
		// deaktiviert wird.
		/*
		 * for (String key : controlMap.keySet()) { for (Control c :
		 * controlMap.get(key)) { c.addListener(SWT.Selection, new Listener() {
		 * 
		 * @Override public void handleEvent(Event event) { if (event.type ==
		 * SWT.Selection) { //TODO: Wenn wieder der Standardwert eingestellt
		 * wird, dann soll die Checkbox aktiviert werden
		 * button.setSelection(false); } } }); } }
		 */

		// Inherit-Checkbox führt zu (De-)Aktivierung der Combobox
		inherit.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				boolean controlToShow;
				
				if (!inherit.getSelection()
						|| format.getType().equals("standard")) {
					// Wenn eigene Werte definieren, alle Control aktivieren
					controlToShow = true;
					for (String key : controlMap.keySet()) {
						for (Control c : controlMap.get(key)) {
							c.setEnabled(controlToShow);
						}
						if (format.getType().equals("standard")) {
							format.switchInherit(key);
						} else {
							format.setInherit(key, false);
						}
					}

					// mit Checkbox verbundene Spinner/Combo muss deaktiviert
					// werden,
					// wenn Checkbox false ist
					if (checkBoxMap != null)
						for (String key : checkBoxMap.keySet()) {
							Button checkbox = (Button) checkBoxMap.get(key);
							if (inArray(key, checkboxArr)
									&& !checkbox.getSelection()) {
								for (Control spinnerOrCombo : controlMap
										.get(key)) {
									spinnerOrCombo.setEnabled(false);
								}
							}

						}
				} else {
					controlToShow = false;
					// klicken, Standardwerte einsetzen
					Control[] controls;
					String standardValue = "";
					for (String key : controlMap.keySet()) {
						format.setInherit(key, true);
						
						/*if (format.getFormatGroup() != null)
							standardValue = format.getFormatGroup().getStandardFormat().getAttribute(key);
						*/
						controls = controlMap.get(key);
						//setControlsValue(controls, standardValue, key);

						if (key.equals("font-family")) { // if font-family is inherited -> check for consequences for font-variant
							controls[0].notifyListeners(SWT.Selection, new Event());
						}
						
						// wenn key hängt mit checkbox zusammen.
						if (checkBoxMap != null && checkBoxMap.get(key) != null
								&& inArray(key, checkboxArr)) {
							Button checkbox = (Button) checkBoxMap.get(key);
							if (standardValue.equals(""))
								checkbox.setSelection(false);
							else
								checkbox.setSelection(true);
						}

						for (Control c : controls)
							c.setEnabled(controlToShow);
					}
				}

				if (checkBoxMap != null)
					for (String key : checkBoxMap.keySet()) {
						checkBoxMap.get(key).setEnabled(controlToShow);
					}
			}
		});

		standardButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// boolean controlToShow;

				Control[] controls;
				String standardValue = "";
				for (String key : controlMap.keySet()) {

					if (format.getFormatGroup() != null)
						standardValue = format.getFormatGroup()
								.getStandardFormat().getAttribute(key);

					controls = controlMap.get(key);

					if (key == "language") {
						if (format.getFormatGroup().getStandardFormat().getAttribute("country").equals("")){ //no country code given
							setControlsValue(controls, standardValue + ":" + standardValue, key);
						} else {
							setControlsValue(controls, standardValue + ":" + format.getFormatGroup().getStandardFormat().getAttribute("country"), key);
						}
					} else if (key == "country")
						;//
					else
						setControlsValue(controls, standardValue, key);

					if (key.equals("font-family")) { // if font-family is inherited -> check for consequences for font-variant
						controls[0].notifyListeners(SWT.Selection, new Event());
					}
					
					// wenn key hängt mit checkbox zusammen.
					if (checkBoxMap != null && checkBoxMap.get(key) != null
							&& inArray(key, checkboxArr)) {
						Button checkbox = (Button) checkBoxMap.get(key);
						if (standardValue.equals(""))
							checkbox.setSelection(false);
						else
							checkbox.setSelection(true);
					}
				}
				if (checkBoxMap != null && checkBoxMap.containsKey("hyphenate")) {
						//checkBoxMap.get("hyphenate") != null) {
					Button checkbox = (Button) checkBoxMap.get("hyphenate");
					if (format.getFormatGroup()
							.getStandardFormat().getAttribute("hyphenate")
							.equals("true"))
						checkbox.setSelection(true);
					else
						checkbox.setSelection(false);
				}
				
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}
		});

		/*
		 * button.addSelectionListener(new SelectionAdapter() { public void
		 * widgetSelected(SelectionEvent e) { boolean controlToShow;
		 * 
		 * if (!button.getSelection()) { // Wenn eigene Werte definieren, alle
		 * Control aktivieren //controlToShow = true; //for (String key :
		 * controlMap.keySet()) { // for (Control c : controlMap.get(key)) //
		 * c.setEnabled(controlToShow); //}
		 * 
		 * // mit Checkbox verbundene Spinner/Combo muss deaktiviert // werden,
		 * // wenn Checkbox false ist //if (checkBoxMap != null) //for (String
		 * key : checkBoxMap.keySet()) { //Button checkbox = (Button)
		 * checkBoxMap.get(key); //if (inArray(key, checkboxArr) // &&
		 * !checkbox.getSelection()) { //for (Control spannerOrCombo :
		 * controlMap // .get(key)) { //spannerOrCombo.setEnabled(false); //}
		 * //}
		 * 
		 * //} } else { //controlToShow = false; // klicken, Standardwerte
		 * einsetzen Control[] controls; String standardValue = ""; for (String
		 * key : controlMap.keySet()) {
		 * 
		 * if (format.getFormatGroup() != null) standardValue =
		 * format.getFormatGroup() .getStandardFormat().getAttribute(key);
		 * 
		 * controls = controlMap.get(key);
		 * 
		 * setControlsValue(controls, standardValue, factor, key);
		 * 
		 * // wenn key hängt mit checkbox zusammen. if (checkBoxMap != null &&
		 * checkBoxMap.get(key) != null && inArray(key, checkboxArr)) { Button
		 * checkbox = (Button) checkBoxMap.get(key); if
		 * (standardValue.equals("")) checkbox.setSelection(false); else
		 * checkbox.setSelection(true); }
		 * 
		 * //for (Control c : controls) //c.setEnabled(controlToShow); } }
		 * 
		 * //if (checkBoxMap != null) //for (String key : checkBoxMap.keySet())
		 * { //checkBoxMap.get(key).setEnabled(controlToShow); //} }});
		 */

		Control[] controls;
		String controlValue = "";

		// zeilenweise Schleife
		for (String attrName : controlMap.keySet()) {
			controls = controlMap.get(attrName);

			boolean buttonEnabled = true;
			// normale Formatwerte
			controlValue = format.getAttribute(attrName);
			//System.out.println(attrName + ": " + controlValue);

			if (format != null && format.getType().equals("standard")) {
				// Format ist Standard
				buttonEnabled = false;
				// format.setInherit(attrName, false); //Inherit deaktiviert
				// setControlsValue(controls, controlValue, factor, attrName);
			} else if (format != null
					&& format.getRealAttribute(attrName).equals("%@%")) {
				// wenn Werte aus Standard soll

				if (format.getFormatGroup() != null)
					controlValue = format.getFormatGroup().getStandardFormat()
							.getAttribute(attrName);
				else
					controlValue = "";

				/*
				 * for (Control c : controls) { c.setEnabled(false); }
				 */

				// button.setSelection(true);
			}

			if (format != null) {
				if (format.isInherit(attrName)) {
					// wenn Werte vererbt werden
					if (!format.getType().equals("standard")) {
						for (Control c : controls) {
							c.setEnabled(false);
						}
					}
					inherit.setSelection(true);
				} else {
					inherit.setSelection(false);
				}
			}

			standardButton.setEnabled(buttonEnabled);
			inherit.setEnabled(true);
			if (!buttonEnabled) {
				inherit.setSelection(false);
				inherit.setEnabled(false);
			}
			
			// For "language:country" the setting has to be modified
			if (attrName.equals("language")) {
				if (format.getAttribute(attrName).equals("")) { // old file without hyphenation->set default language
					setControlsValue(controls, "de:DR", attrName);
					format.setInherit("hyphenate", true);
					format.setInherit("language", true);
					format.setInherit("country", true);
					inherit.setSelection(true);
					controls[0].setEnabled(false);
				} else {
					if (format.getAttribute("country").equals("")){ //no country code given
						setControlsValue(controls, controlValue + ":" + controlValue, attrName);
					} else {
						setControlsValue(controls, controlValue + ":" + format.getAttribute("country"), attrName);
					}
				}
			}
			else if (attrName.equals("country"))
				;//
			else if (attrName.equals("hyphenation-remain-character-count")) {
				if (format.getAttribute("language").equals("")) {
					setControlsValue(controls, "2", attrName);
					format.setInherit(attrName, true);
					inherit.setSelection(true);
					controls[0].setEnabled(false);
				}
				else
					setControlsValue(controls, controlValue, attrName);
			}
			else if (attrName.equals("hyphenation-push-character-count")) {
				if (format.getAttribute("language").equals("")) {
					setControlsValue(controls, "2", attrName);
					format.setInherit(attrName, true);
					inherit.setSelection(true);
					controls[0].setEnabled(false);
				}
				else
					setControlsValue(controls, controlValue, attrName);
			}
			else
				setControlsValue(controls, controlValue, attrName);
		}

		// checkboxs
		if (checkBoxMap != null)
			for (String key : checkBoxMap.keySet()) {
				Button checkbox = (Button) checkBoxMap.get(key);
				// wenn (before/after) Maximum/ Minimum Werte hat
				if (inArray(key, checkboxArr)
						&& !format.getAttribute(key).equals("")) {
					checkbox.setSelection(true);
					if (!inherit.getSelection())
						for (Control spannerOrCombo : controlMap.get(key)) {
							spannerOrCombo.setEnabled(true);
						}
				}

				if (inherit.getSelection()
						&& !format.getType().equals("standard"))
					checkbox.setEnabled(false);
			}
	}

	/*
	 * 
	 */
	private void setControlsValue(Control[] controls, String controlValue,
			String attrName) {

		controlValue = getLocalValue(attrName, controlValue);

		Combo combo = null;
		Spinner spinner = null;

		if (controls.length == 2 && controls[0] instanceof Spinner
				&& controls[1] instanceof Combo) { // spinner + combo
			spinner = (Spinner) controls[0];
			combo = (Combo) controls[1];
			setSpinnerCombo(spinner, combo, controlValue);
		} else if (controls.length == 1 && controls[0] instanceof Combo) { // nur combo
			combo = (Combo) controls[0];
			setCombo(combo, controlValue);
		} else if (controls.length == 1 && controls[0] instanceof Spinner) {
			spinner = (Spinner) controls[0];
			if (controlValue.equals("")) //for empty value due to new feature vs. old file set spinner to minimum
				spinner.setSelection(spinner.getMinimum());
			else
				spinner.setSelection(Integer.parseInt(controlValue));
		}
	}

	private boolean inArray(String s, String[] arr) {
		for (String str : arr) {
			if (s.equals(str))
				return true;
		}
		return false;
	}

	protected void formatValueToInternational(String[] realArr,
			String[] newArr, Format f, String attr) {

		for (int i = 0; i < realArr.length; i++) {
			String realStr = realArr[i];

			if (f.getAttribute(attr).equals(realStr)) {
				f.setAttribute(attr, newArr[i]);
			}

		}
	}

	protected void addInternationalMap(String key, String[] original,
			String[] local) {
		InternationalTransform it = new InternationalTransform();
		it.setOriginal(original);
		it.setLocal(local);
		internationalMap.put(key, it);
	}

	protected String getOriginalValue(String key, String value) {
		InternationalTransform it = internationalMap.get(key);
		if (it != null) {
			value = it.getOriginalValue(value);
		}
		return value;
	}

	protected String getLocalValue(String key, String value) {
		InternationalTransform it = internationalMap.get(key);
		if (it != null) {
			value = it.getLocalValue(value);
		}
		return value;
	}
}

class InternationalTransform {
	private String[] original;
	private String[] local;

	public String[] getOriginal() {
		return original;
	}

	public void setOriginal(String[] original) {
		this.original = original;
	}

	public String[] getLocal() {
		return local;
	}

	public void setLocal(String[] local) {
		this.local = local;
	}

	public String getOriginalValue(String localValue) {
		if (localValue == null || localValue.equals(""))
			return "";

		for (int i = 0; i < local.length; i++) {
			if (localValue.equals(local[i]))
				return original[i];
		}
		return "";
	}

	public String getLocalValue(String originalValue) {
		if (originalValue == null || originalValue.equals(""))
			return "";

		for (int i = 0; i < original.length; i++) {
			if (originalValue.equals(original[i]))
				return local[i];
		}
		return "";

	}

}
